﻿using System;
using System.Collections.Generic;

namespace Framework.Event
{
    /// <summary>
    /// 事件池
    /// </summary>
    public class EventPool<T> where T : IEventArg
    {
        private Dictionary<int, EventHandler<T>> m_Handlers;
        private Queue<Event<T>> m_Events;

        /// <summary>
        /// 事件池构造函数
        /// </summary>
        public EventPool()
        {
            m_Handlers = new Dictionary<int, EventHandler<T>>();
            m_Events = new Queue<Event<T>>();
        }
        /// <summary>
        /// 事件数量
        /// </summary>
        public int EventCount
        {
            get
            {
                return m_Events.Count;
            }
        }
        /// <summary>
        /// 订阅事件
        /// </summary>
        /// <param name="eventId">事件Id</param>
        /// <param name="handler">事件回调函数</param>
        public void Subscriber(int eventId, EventHandler<T> handler)
        {
            if (handler == null) return;
            EventHandler<T> temp = null;
            if(m_Handlers.TryGetValue(eventId, out temp))
            {
                temp += handler;
                m_Handlers[eventId] = temp;
            }
            else
            {
                temp = handler;
                m_Handlers[eventId] = temp;
            }
        }
        /// <summary>
        /// 取消订阅时间
        /// </summary>
        /// <param name="eventId">事件Id</param>
        /// <param name="handler">时间回调函数</param>
        public void UnSubscriber(int eventId, EventHandler<T> handler)
        {
            if (handler == null) return;
            if(m_Handlers.ContainsKey(eventId))
            {
                m_Handlers[eventId] -= handler;
            }
        }
        /// <summary>
        /// 清空所有事件
        /// </summary>
        public void Clear()
        {
            if(m_Events != null)
                m_Events.Clear();
        }
        /// <summary>
        /// 销毁方法
        /// </summary>
        public void Destroy()
        {
            if(m_Events != null)
                m_Events.Clear();
            if (m_Handlers != null)
                m_Handlers.Clear();
        }
        /// <summary>
        /// 抛出事件
        /// </summary>
        /// <param name="sender">时间抛出对象</param>
        /// <param name="arg">事件参数</param>
        public void Fire(object sender, T arg)
        {
            Event<T> e = new Event<T>(sender, arg);
            lock(m_Events)
            {
                m_Events.Enqueue(e);
            }
        }
        /// <summary>
        /// 立刻抛出事件
        /// </summary>
        /// <param name="sender">事件抛出对象</param>
        /// <param name="arg">事件参数</param>
        public void FireNow(object sender, T arg)
        {
            HandleEvent(sender, arg);
        }
        /// <summary>
        /// 轮询函数
        /// </summary>
        /// <param name="frameTime">逻辑一帧时间</param>
        /// <param name="realTime">实际一帧时间</param>
        public void Update(float frameTime, float realTime)
        {
            while(m_Events.Count > 0)
            {
                Event<T> e = null;
                lock(m_Events)
                {
                    e = m_Events.Dequeue();
                }
                HandleEvent(e.Sender, e.Args);
            }
        }
        private void HandleEvent(object sender, T arg)
        {
            EventHandler<T> handler = null;
            if(m_Handlers.TryGetValue(arg.EventId, out handler))
            {
                if(handler != null)
                {
                    handler(sender, arg);
                    ReferencePool.Collect(typeof(T), arg);
                }
            }
        }
    }
}
